#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
Author: Roger
License: wtfpl
'''
import docx
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from docx.shared import Pt, RGBColor

# global variables
file2 = docx.Document() # target file
levelset = set()
metHead = False

# print("段落数：" + str(len(file.paragraphs)))

'''
for para in file.paragraphs:
    print("内容是：" + para.text)
'''


def getParaLevel(para):
    if para is not None and \
            para.paragraph_format is not None and \
            para.paragraph_format.element is not None and \
            para.paragraph_format.element.xml is not None:
        xml = (para.paragraph_format.element.xml)

        if xml.find('<w:pStyle w:val=') >= 0:
            start_index = xml.find('<w:pStyle w:val=')
            end_index = xml.find('>', start_index)
            # print("第段的val是：" + str(xml[start_index + len('<w:pStyle w:val=') + 1:end_index - 2]))
            return str(xml[start_index + len('<w:pStyle w:val=') + 1:end_index - 2])

    return None


def getParaStyleName(para):
    '''

    :param para:
    :return:
    '''
    if para is not None and \
            para.style is not None and \
            para.style.name is not None:
        return para.style.name
    else:
        return None


def scanDoc(doc):
    '''

    :param doc:
    :return:
    '''
    print("There are {} paragraphs".format(len(doc.paragraphs)))

    # check if the levels exceed 4

    for para in doc.paragraphs:
        level = getParaLevel(para)
        styleName = getParaStyleName(para)

        if level is not None and \
                styleName.startswith('Heading'): #只有Heading 开头的syle才算入
            levelset.add(level)
        else:  # 正文
            continue
    if len(levelset) >= 4:
        print("Warning! there are more than 4 levels")
        return False


def setTitle(para):
    '''

    :param para:
    :return:
    '''
    file2.add_paragraph('')
    file2.add_paragraph('')  # 标题上方控2-3行
    out_para = file2.add_paragraph(para.text)
    out_para.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  # 居中
    # out_para.style = 'Title' 这个会引出一条分割线
    for run in out_para.runs:
        run.font.size = Pt(22)  # 二号字体
        run.font.name = u'Times New Roman'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')


def firstLevel(level):
    '''

    :param level: The absolute level
    :return:
    if the absolute is the highest level(smallest number)
    return True,
    return False otherwise
    '''
    if len(levelset) < 1:
        return False

    sorted_list = sorted(levelset)

    if sorted_list[0] == level:
        return True
    return False

def secondLevel(level):
    if len(levelset) < 2:
        return False
    sorted_list = sorted(levelset)

    if sorted_list[1] == level:
        return True
    return False


def thirdLevel(level):
    if len(levelset) < 3:
        return False
    sorted_list = sorted(levelset)
    if sorted_list[2] == level:
        return True
    return False


def forthLevel(level):
    if len(levelset) < 4:
        return False
    sorted_list = sorted(levelset)
    if sorted_list[3] == level:
        return True
    return False


def globalSet(para):
    '''
    全文两端对齐，行前行后0，行间距28磅
    :param para:
    :return:
    '''
    para.paragraph_format.space_before = Pt(0)
    para.paragraph_format.space_after = Pt(0)
    para.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
    para.paragraph_format.line_spacing = Pt(28)
    para.paragraph_format.first_line_indent = 0
    para.paragraph_format.element.pPr.ind.set(qn("w:firstLineChars"), '200')  # 设置首行缩减2个字符的正确方法

def setFirstLevel(para):
    '''
    setFirstLevel,三号，黑体，不加粗
    :param para:
    :return:
    '''
    out_para = file2.add_paragraph(para.text)
    out_para.style = 'Heading 1'
    globalSet(out_para)
    for run in out_para.runs:
        run.font.size = Pt(16)  # 三号字体
        run.font.color.rgb = RGBColor(0, 0, 0)
        run.font.name = u'Times New Roman'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), u'黑体')


def setSecondLevel(para):
    '''
    setFirstLevel,三号，楷体GB2312或者楷体，加粗
    :param para:
    :return:
    '''
    out_para = file2.add_paragraph(para.text)
    out_para.style = 'Heading 2'
    globalSet(out_para)
    for run in out_para.runs:
        run.font.size = Pt(16)  # 三号字体
        run.font.color.rgb = RGBColor(0, 0, 0)
        run.font.name = u'Times New Roman'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), u'楷体GB2312')
        run.font.bold = True


def setThirdLevel(para):
    '''
    setFirstLevel,三号，仿宋GB2312或者仿宋，视情况加粗
    :param para:
    :return:
    '''
    out_para = file2.add_paragraph(para.text)
    out_para.style = 'Heading 3'
    globalSet(out_para)
    for run in out_para.runs:
        run.font.size = Pt(16)  # 三号字体
        run.font.color.rgb = RGBColor(0, 0, 0)
        run.font.name = u'Times New Roman'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋GB2312')
        # run.font.bold = True


def setForthLevel(para):
    '''
    setFirstLevel,三号，仿宋GB2312或者仿宋，视情况加粗
    :param para:
    :return:
    '''
    out_para = file2.add_paragraph(para.text)
    out_para.style = 'Heading 4'
    globalSet(out_para)
    for run in out_para.runs:
        run.font.size = Pt(16)  # 三号字体
        run.font.color.rgb = RGBColor(0, 0, 0)
        run.font.name = u'Times New Roman'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋GB2312')
        # run.font.bold = True


def setNormal(para):
    '''
    原则上，全文段前、段后0行，行间距为28磅；每段首行缩进2字符，
    文本之前、文本之后0字符。正文使用仿宋GB2312或仿宋，数字、字母等使用Times New Roman字体。
    对齐方式：全文选择两端对齐。
    :param para:
    :return:
    '''
    out_para = file2.add_paragraph(para.text)
    out_para.style = 'Normal'
    globalSet(out_para)

    for run in out_para.runs:
        run.font.size = Pt(16)  # 三号字体
        run.font.color.rgb = RGBColor(0, 0, 0)
        run.font.name = u'Times New Roman'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋GB2312')
        # run.font.bold = True


def fixParagraph(para):
    '''
    fix a para according to the guidance and save it to file2
    :param para:
    :return: none
    '''
    global metHead
    level = getParaLevel(para)
    styleName = getParaStyleName(para)

    if len(para.text) == 0:
        return None

    if level is not None:
        if styleName == 'Title':
            setTitle(para)
        elif firstLevel(level):
            setFirstLevel(para)
        elif secondLevel(level):
            setSecondLevel(para)
        elif thirdLevel(level):
            setThirdLevel(para)
        elif forthLevel(level):
            setForthLevel(para)
        else:
            print("Unsupported styleName is: " + styleName + "Handle it as normal")
            setNormal(para)
    else:  # normal
        if metHead == False: # 第一条出现的正文也当成Title
            setTitle(para)
            metHead = True
        else:
            setNormal(para)
    return None


import sys


def main(inputfile):

    print("Working on file: " + inputfile)
    outputfile=inputfile.split('.docx')[0] +'_revised.docx'
    print("Creating：" + outputfile)
    file = docx.Document(inputfile)

    if scanDoc(file) is False:
        exit(-1)

    for para in file.paragraphs:
        fixParagraph(para)

    file2.save(outputfile)


if __name__ == "__main__":
    main(sys.argv[1])
